home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Orpheus v3.02 / SETUP.EXE / %MAINDIR% / OvcDbNum.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-02-25  |  13.8 KB  |  571 lines

  1. {*********************************************************}
  2. {*                   OVCDBNUM.PAS 3.00                   *}
  3. {*     Copyright (c) 1995-99 TurboPower Software Co      *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I OVC.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17. {$G+} {286 Instructions}
  18. {$N+} {Numeric Coprocessor}
  19.  
  20. {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  21. {$ENDIF}
  22.  
  23. unit OvcDbNum;
  24.   {-Data aware number edit field w/ popup calculator}
  25.  
  26. interface
  27.  
  28. uses
  29.   {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  30.   Classes, Controls, Db, DbConsts, DbCtrls, {$IFNDEF VERSION3} DbTables, {$ENDIF}
  31.   Forms, Graphics, Menus, Messages, StdCtrls, SysUtils,
  32.   OvcBase, OvcCalc, OvcEdClc, OvcEdPop, OvcEditF;
  33.  
  34. type
  35.   TOvcCustomDbNumberEdit = class(TOvcCustomNumberEdit)
  36.   {.Z+}
  37.   protected {private}
  38.     FAlignment  : TAlignment;
  39.     FAutoUpdate : Boolean;
  40.     FCanvas     : TControlCanvas;
  41.     FDataLink   : TFieldDataLink;
  42.     FFocused    : Boolean;
  43.  
  44.     {property methods}
  45.     function GetDataField : string;
  46.     function GetDataSource : TDataSource;
  47.     function GetField : TField;
  48.     function GetReadOnly : Boolean;
  49.     procedure SetDataField(const Value : string);
  50.     procedure SetDataSource(Value : TDataSource);
  51.     procedure SetFocused(Value : Boolean);
  52.     procedure SetReadOnly(Value : Boolean);
  53.  
  54.     {internal methods}
  55.     procedure DataChange(Sender : TObject);
  56.     procedure EditingChange(Sender : TObject);
  57.     function GetTextMargins : TPoint;
  58.     procedure UpdateData(Sender : TObject);
  59.  
  60.     {message methods}
  61.     procedure WMCut(var Message : TMessage);
  62.       message WM_CUT;
  63.     procedure WMPaste(var Message : TMessage);
  64.       message WM_PASTE;
  65.     procedure WMPaint(var Message : TWMPaint);
  66.       message WM_PAINT;
  67.     procedure CMEnter(var Message : TCMEnter);
  68.       message CM_ENTER;
  69.     procedure CMExit(var Message : TCMExit);
  70.       message CM_EXIT;
  71.     {$IFDEF Win32}
  72.     procedure CMGetDataLink(var Message : TMessage);
  73.       message CM_GETDATALINK;
  74.     {$ENDIF Win32}
  75.  
  76.   protected
  77.     procedure Change;
  78.       override;
  79.     function GetButtonEnabled : Boolean;
  80.       override;
  81.     procedure KeyDown(var Key : Word; Shift : TShiftState);
  82.       override;
  83.     procedure KeyPress(var Key : Char);
  84.       override;
  85.     procedure Notification(AComponent : TComponent; Operation : TOperation);
  86.       override;
  87.   {.Z-}
  88.  
  89.     {protected properties}
  90.     property AutoUpdate : Boolean
  91.       read FAutoUpdate
  92.       write FAutoUpdate;
  93.  
  94.     property DataField : string
  95.       read GetDataField
  96.       write SetDataField;
  97.  
  98.     property DataSource : TDataSource
  99.       read GetDataSource
  100.       write SetDataSource;
  101.  
  102.   {.Z+}
  103.     property ReadOnly : Boolean {hides ancestor's ReadOnly property}
  104.       read GetReadOnly
  105.       write SetReadOnly;
  106.  
  107.   public
  108.     constructor Create(AOwner : TComponent);
  109.       override;
  110.     destructor Destroy;
  111.       override;
  112.     {$IFDEF VERSION4}
  113.     function ExecuteAction(Action: TBasicAction): Boolean;
  114.       override;
  115.     function UpdateAction(Action: TBasicAction): Boolean;
  116.       override;
  117.     {$ENDIF}
  118.  
  119.     procedure PopupClose(Sender : TObject);
  120.       override;
  121.     procedure PopupOpen;
  122.       override;
  123.   {.Z-}
  124.  
  125.     {public properties}
  126.     property Field : TField
  127.       read GetField;
  128.   end;
  129.  
  130.   TOvcDbNumberEdit = class(TOvcCustomDbNumberEdit)
  131.   published
  132.     {properties}
  133.     {$IFDEF VERSION4}
  134.     property Anchors;
  135.     property Constraints;
  136.     property DragKind;
  137.     {$ENDIF}
  138.     property About;
  139.     property AllowIncDec;
  140.     property AutoSelect;
  141.     property AutoSize;
  142.     property AutoUpdate;
  143.     property BorderStyle;
  144.     property ButtonGlyph;
  145.     property Color;
  146.     property Ctl3D;
  147.     property Cursor;
  148.     property DataField;
  149.     property DataSource;
  150.     property DragCursor;
  151.     property DragMode;
  152.     property Enabled;
  153.     property LabelInfo;
  154.     property Font;
  155.     property HideSelection;
  156.     property ParentColor;
  157.     property ParentCtl3D;
  158.     property ParentFont;
  159.     property ParentShowHint;
  160.     property PopupAnchor;
  161.     property PopupColors;
  162.     property PopupFont;
  163.     property PopupHeight;
  164.     property PopupMenu;
  165.     property PopupWidth;
  166.     property ReadOnly;
  167.     property ShowButton;
  168.     property ShowHint;
  169.     property TabOrder;
  170.     property TabStop;
  171.     property Visible;
  172.  
  173.     {events}
  174.     property OnChange;
  175.     property OnClick;
  176.     property OnDblClick;
  177.     property OnDragDrop;
  178.     property OnDragOver;
  179.     property OnEndDrag;
  180.     property OnEnter;
  181.     property OnExit;
  182.     property OnKeyDown;
  183.     property OnKeyPress;
  184.     property OnKeyUp;
  185.     property OnMouseDown;
  186.     property OnMouseMove;
  187.     property OnMouseUp;
  188.     {$IFDEF Win32}
  189.     property OnStartDrag;
  190.     {$ENDIF Win32}
  191.   end;
  192.  
  193.  
  194. implementation
  195.  
  196. const
  197.   NumFieldTypes : set of  TFieldType =
  198.     [ftSmallInt, ftInteger, ftWord, ftFloat, ftCurrency, ftBCD];
  199.  
  200.  
  201. {*** TOvcCustomDbNumberEdit ***}
  202.  
  203. procedure TOvcCustomDbNumberEdit.Change;
  204. begin
  205.   FDataLink.Modified;
  206.  
  207.   inherited Change;
  208. end;
  209.  
  210. procedure TOvcCustomDbNumberEdit.CMEnter(var Message : TCMEnter);
  211. begin
  212.   SetFocused(True);
  213.  
  214.   inherited;
  215. end;
  216.  
  217. procedure TOvcCustomDbNumberEdit.CMExit(var Message : TCMExit);
  218. begin
  219.   if PopupActive then
  220.     Exit;
  221.  
  222.   if AutoUpdate then begin
  223.     try
  224.       if Modified then
  225.         FDataLink.UpdateRecord;
  226.     except
  227.       SelectAll;
  228.       SetFocus;
  229.       raise;
  230.     end;
  231.   end;
  232.   SetFocused(False);
  233.   DoExit;
  234. end;
  235.  
  236. {$IFDEF Win32}
  237. procedure TOvcCustomDbNumberEdit.CMGetDataLink(var Message : TMessage);
  238. begin
  239.   Message.Result := Integer(FDataLink);
  240. end;
  241. {$ENDIF Win32}
  242.  
  243. constructor TOvcCustomDbNumberEdit.Create(AOwner : TComponent);
  244. begin
  245.   inherited Create(AOwner);
  246.  
  247.   inherited ReadOnly := True;
  248.  
  249.   {$IFDEF Win32}
  250.   ControlStyle := ControlStyle + [csReplicatable];
  251.   {$ENDIF Win32}
  252.  
  253.   FAutoUpdate := True;
  254.   FDataLink := TFieldDataLink.Create;
  255.   FDataLink.Control := Self;
  256.   FDataLink.OnDataChange := DataChange;
  257.   FDataLink.OnEditingChange := EditingChange;
  258.   FDataLink.OnUpdateData := UpdateData;
  259. end;
  260.  
  261. procedure TOvcCustomDbNumberEdit.DataChange(Sender : TObject);
  262. var
  263.   P : Integer;
  264.   S : string[80];
  265. begin
  266.   if FDataLink.Field <> nil then begin
  267.     if FAlignment <> FDataLink.Field.Alignment then begin
  268.       FAlignment := FDataLink.Field.Alignment;
  269.       Text := '';
  270.     end;
  271.     if FDataLink.Field.DataType in NumFieldTypes then begin
  272.       if FFocused and FDataLink.CanModify then
  273.         Text := FDataLink.Field.Text
  274.       else
  275.         Text := FDataLink.Field.DisplayText;
  276.     end else begin
  277.       S := FDataLink.Field.ClassName;
  278.       S[1] := '(';
  279.       P := Pos('Field', S);
  280.       if P > 0 then begin
  281.         S[P] := ')';
  282.         S[0] := Char(P);
  283.       end else
  284.         S := Concat(S, ')');
  285.       Text := S;
  286.     end;
  287.   end else begin
  288.     FAlignment := taLeftJustify;
  289.     if csDesigning in ComponentState then
  290.       Text := Name
  291.     else
  292.       Text := '';
  293.   end;
  294. end;
  295.  
  296. destructor TOvcCustomDbNumberEdit.Destroy;
  297. begin
  298.   FDataLink.Free;
  299.   FDataLink := nil;
  300.  
  301.   FCanvas.Free;
  302.   FCanvas := nil;
  303.  
  304.   inherited Destroy;
  305. end;
  306.  
  307. procedure TOvcCustomDbNumberEdit.EditingChange(Sender : TObject);
  308. begin
  309.   inherited ReadOnly := not FDataLink.Editing;
  310.   FButton.Enabled := GetButtonEnabled;
  311. end;
  312.  
  313. function TOvcCustomDbNumberEdit.GetButtonEnabled : Boolean;
  314. begin
  315.   Result := (FDataLink <> nil) and (FDataLink.DataSource <> nil) and
  316.     (FDataLink.Editing or FDataLink.DataSource.AutoEdit) or
  317.     (csDesigning in ComponentState);
  318. end;
  319.  
  320. function TOvcCustomDbNumberEdit.GetDataField : string;
  321. begin
  322.   Result := FDataLink.FieldName;
  323. end;
  324.  
  325. function TOvcCustomDbNumberEdit.GetDataSource : TDataSource;
  326. begin
  327.   Result := FDataLink.DataSource;
  328. end;
  329.  
  330. function TOvcCustomDbNumberEdit.GetField : TField;
  331. begin
  332.   Result := FDataLink.Field;
  333. end;
  334.  
  335. function TOvcCustomDbNumberEdit.GetReadOnly : Boolean;
  336. begin
  337.   Result := FDataLink.ReadOnly;
  338.   if FDataLink.Field <> nil then
  339.     if not (FDataLink.Field.DataType in NumFieldTypes) then
  340.       Result := True;
  341. end;
  342.  
  343. function TOvcCustomDbNumberEdit.GetTextMargins : TPoint;
  344. var
  345.   DC         : HDC;
  346.   SaveFont   : HFont;
  347.   I          : Integer;
  348.   SysMetrics : TTextMetric;
  349.   Metrics    : TTextMetric;
  350. begin
  351.   if NewStyleControls then begin
  352.     if BorderStyle = bsNone then
  353.       I := 0
  354.     else if Ctl3D then
  355.       I := 1
  356.     else
  357.       I := 2;
  358.     {$IFDEF Win32}
  359.     Result.X := SendMessage(Handle, EM_GETMARGINS, 0, 0) and $0000FFFF + I;
  360.     {$ELSE}
  361.     Result.X := 2;
  362.     {$ENDIF Win32}
  363.     Result.Y := I;
  364.   end else begin
  365.     if BorderStyle = bsNone then
  366.       I := 0
  367.     else begin
  368.       DC := GetDC(0);
  369.       GetTextMetrics(DC, SysMetrics);
  370.       SaveFont := SelectObject(DC, Font.Handle);
  371.       GetTextMetrics(DC, Metrics);
  372.       SelectObject(DC, SaveFont);
  373.       ReleaseDC(0, DC);
  374.       I := SysMetrics.tmHeight;
  375.       if I > Metrics.tmHeight then
  376.         I := Metrics.tmHeight;
  377.       I := I div 4;
  378.     end;
  379.     Result.X := I;
  380.     Result.Y := I;
  381.   end;
  382. end;
  383.  
  384. procedure TOvcCustomDbNumberEdit.KeyDown(var Key : Word; Shift : TShiftState);
  385. begin
  386.   inherited KeyDown(Key, Shift);
  387.  
  388.   {start edit mdoe if cutting or pasting}
  389.   if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then
  390.     FDataLink.Edit;
  391. end;
  392.  
  393. procedure TOvcCustomDbNumberEdit.KeyPress(var Key : Char);
  394. begin
  395.   if AllowIncDec and (Key in ['+', '-']) then
  396.     FDataLink.Edit;
  397.  
  398.   inherited KeyPress(Key);
  399.  
  400.   if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  401.      not FDataLink.Field.IsValidChar(Key) then begin
  402.     MessageBeep(0);
  403.     Key := #0;
  404.   end;
  405.  
  406.   case Key of
  407.     ^H, ^V, ^X, #32..#255 :
  408.       FDataLink.Edit;
  409.     #27:
  410.       begin
  411.         FDataLink.Reset;
  412.         SelectAll;
  413.         Key := #0;
  414.       end;
  415.   end;
  416. end;
  417.  
  418. procedure TOvcCustomDbNumberEdit.Notification(AComponent : TComponent; Operation : TOperation);
  419. begin
  420.   inherited Notification(AComponent, Operation);
  421.  
  422.   if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then
  423.     DataSource := nil;
  424. end;
  425.  
  426. procedure TOvcCustomDbNumberEdit.PopupClose(Sender : TObject);
  427. begin
  428.   inherited PopupClose(Sender);
  429.  
  430.   {allow control to see focus change that was blocked when popup became active}
  431.   if not Focused then
  432.     Perform(CM_EXIT, 0, 0);
  433. end;
  434.  
  435. procedure TOvcCustomDbNumberEdit.PopupOpen;
  436. begin
  437.   inherited PopupOpen;
  438.  
  439.   {enter edit mode}
  440.   FDataLink.Edit;
  441. end;
  442.  
  443. procedure TOvcCustomDbNumberEdit.SetDataField(const Value : string);
  444. begin
  445.   try
  446.     FDataLink.FieldName := Value;
  447.   except
  448.     FDataLink.FieldName := '';
  449.     raise;
  450.   end;
  451. end;
  452.  
  453. procedure TOvcCustomDbNumberEdit.SetDataSource(Value : TDataSource);
  454. begin
  455.   FDataLink.DataSource := Value;
  456.   {$IFDEF Win32}
  457.   if Value <> nil then
  458.     Value.FreeNotification(Self);
  459.   {$ENDIF Win32}
  460. end;
  461.  
  462. procedure TOvcCustomDbNumberEdit.SetFocused(Value : Boolean);
  463. begin
  464.   if FFocused <> Value then begin
  465.     FFocused := Value;
  466.     if (FAlignment <> taLeftJustify) then
  467.       Invalidate;
  468.     FDataLink.Reset;
  469.   end;
  470. end;
  471.  
  472. procedure TOvcCustomDbNumberEdit.SetReadOnly(Value : Boolean);
  473. begin
  474.   FDataLink.ReadOnly := Value;
  475. end;
  476.  
  477. procedure TOvcCustomDbNumberEdit.UpdateData(Sender : TObject);
  478. begin
  479.   FDataLink.Field.Text := Text;
  480. end;
  481.  
  482. procedure TOvcCustomDbNumberEdit.WMCut(var Message : TMessage);
  483. begin
  484.   FDataLink.Edit;
  485.  
  486.   inherited;
  487. end;
  488.  
  489. procedure TOvcCustomDbNumberEdit.WMPaint(var Message : TWMPaint);
  490. var
  491.   Left    : Integer;
  492.   Margins : TPoint;
  493.   R       : TRect;
  494.   DC      : HDC;
  495.   PS      : TPaintStruct;
  496.   S       : string;
  497. begin
  498.   {$IFDEF Win32}
  499.   if ((FAlignment = taLeftJustify) or FFocused) and not (csPaintCopy in ControlState) then begin
  500.   {$ELSE}
  501.   if ((FAlignment = taLeftJustify) or FFocused) then begin
  502.   {$ENDIF Win32}
  503.     inherited;
  504.     Exit;
  505.   end;
  506.  
  507.   {draw right and center justify manually unless the edit has the focus}
  508.   if FCanvas = nil then begin
  509.     FCanvas := TControlCanvas.Create;
  510.     FCanvas.Control := Self;
  511.   end;
  512.   DC := Message.DC;
  513.   if DC = 0 then
  514.     DC := BeginPaint(Handle, PS);
  515.   FCanvas.Handle := DC;
  516.   try
  517.     FCanvas.Font := Font;
  518.     with FCanvas do begin
  519.       R := ClientRect;
  520.       if not (NewStyleControls and Ctl3D) and (BorderStyle = bsSingle) then begin
  521.         Brush.Color := clWindowFrame;
  522.         FrameRect(R);
  523.         InflateRect(R, -1, -1);
  524.       end;
  525.       Brush.Color := Color;
  526.       {$IFDEF Win32}
  527.       if (csPaintCopy in ControlState) and (FDataLink.Field <> nil) then begin
  528.         S := FDataLink.Field.DisplayText;
  529.       end else
  530.       {$ENDIF Win32}
  531.         S := Text;
  532.       if PasswordChar <> #0 then FillChar(S[1], Length(S), PasswordChar);
  533.       Margins := GetTextMargins;
  534.       case FAlignment of
  535.         taLeftJustify  : Left := Margins.X;
  536.         taRightJustify : Left := ClientWidth - TextWidth(S) - Margins.X - 2 - GetButtonWidth;
  537.       else
  538.         Left := (ClientWidth - TextWidth(S)) div 2;
  539.       end;
  540.       TextRect(R, Left, Margins.Y, S);
  541.     end;
  542.   finally
  543.     FCanvas.Handle := 0;
  544.     if Message.DC = 0 then
  545.       EndPaint(Handle, PS);
  546.   end;
  547. end;
  548.  
  549. procedure TOvcCustomDbNumberEdit.WMPaste(var Message : TMessage);
  550. begin
  551.   FDataLink.Edit;
  552.  
  553.   inherited;
  554. end;
  555.  
  556. {$IFDEF VERSION4}
  557. function TOvcCustomDbNumberEdit.ExecuteAction(Action : TBasicAction) : Boolean;
  558. begin
  559.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  560.     FDataLink.ExecuteAction(Action);
  561. end;
  562.  
  563. function TOvcCustomDbNumberEdit.UpdateAction(Action : TBasicAction) : Boolean;
  564. begin
  565.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  566.     FDataLink.UpdateAction(Action);
  567. end;
  568. {$ENDIF}
  569.  
  570. end.
  571.